/******************************************************************************
Project    : Real time rtsp server library base on live555
*******************************************************************************
File Name    :  <RealTimeRtspServer.cpp>:  real time rtsp server source file
Module Name  :  
Description  :  None
History      :
 No.   Ver.     Date        Designed by  Comment
-----+--------+----------+------------+---------------------------------------
 001   0.00.01  05/25/2015  <3G@LIURENHUA>   <real time rtsp server source file>
*******************************************************************************/
#include <pthread.h>
#include <MediaSink.hh>
#include "RealTimeRtspServer.h"

/******************************************************************************
  static member initialize
 ******************************************************************************/
 pthread_mutex_t RealTimeRtspServer::mutex = PTHREAD_MUTEX_INITIALIZER;
 u_int16_t RealTimeRtspServer::m_usPort = DEFAULT_PORT;
 
/******************************************************************************
  class functions define
 ******************************************************************************/
RealTimeRtspServer::RealTimeRtspServer(u_int16_t usPort)
{
	//printf("*************enter [%s]*************\n", __func__);
	/* Initialize server media session pointer or exit flag */
	pctSms = NULL;	cExitFlag = 0;	pctRtspSvr = NULL;
	
	/* Begin by setting up our usage environment */
	pctScheduler = BasicTaskScheduler::createNew();
	if( (NULL == pctScheduler) ){
		printf("[%s]create BasicTaskScheduler failed\n", __func__);
		goto FAIL;
	}
	pctEnv = BasicUsageEnvironment::createNew(*pctScheduler);
	if( (NULL == pctEnv) ){
		printf("[%s]create UsageEnvironment failed\n", __func__);
		goto FAIL;
	}
	/* Get rtsp server port */
	pthread_mutex_lock(&mutex);
	if( (0 == usPort) ){
		usPort = m_usPort++;
	}
	pthread_mutex_unlock(&mutex);

	/* Create the RTSP server */
	OutPacketBuffer::maxSize = 600000;
	pctRtspSvr = 
		RTSPServer::createNew(*pctEnv, usPort, NULL);
	if ( (NULL == pctRtspSvr) ) {
		printf("[%s]create RTSPServer failed\n", __func__);
		goto FAIL;
	}
	return;

FAIL:
	if( (NULL != pctEnv) ){
		pctEnv->reclaim();
		pctEnv = NULL;
	}
	if( (NULL != pctScheduler) ){
		delete pctScheduler;
		pctScheduler = NULL;
	}
}

#define CLOSESMS \
	closeAllClientSessionsForServerMediaSession
#define REMOVSMS \
	removeServerMediaSession

void RealTimeRtspServer::vResetRtspServer()
{
	if( (NULL != pctRtspSvr) ){
		if(  (NULL != pctSms) ){
			pctRtspSvr->CLOSESMS(pctSms);
			pctSms->deleteAllSubsessions();
			pctRtspSvr->REMOVSMS(pctSms);
			pctSms = NULL;
		}
	}
}

RealTimeRtspServer::~RealTimeRtspServer()
{
	//printf("*****enter [%s]******\n", __func__);
	if( (NULL != pctRtspSvr) ){
		Medium::close(pctRtspSvr);
		pctRtspSvr = NULL;
	}
 	if( (NULL != pctEnv) ){
		pctEnv->reclaim();
		pctEnv = NULL;
	}
	if( (NULL != pctScheduler) ){
		delete pctScheduler;
		pctScheduler = NULL;
	}
}

RTSPSVR_ERR_et 
 	RealTimeRtspServer::eCreateSMS(
 	char const* pcStrmName, char const* pcInfo, 
 	char const* pcDescription, Boolean bIsSSM, 
 	char const* pcMiscSDPLines)
{
	RTSPSVR_ERR_et eRet = RTSPSVR_ERR_NOERR;
	if( (NULL != pctEnv) && (NULL == pctSms) ){
		pctSms = ServerMediaSession::createNew(
			*pctEnv, pcStrmName, pcInfo, 
			pcDescription, bIsSSM, 
			pcMiscSDPLines);
		if( (NULL == pctSms) ){
			printf("[%s]create SMS failed\n", 
				__func__);
			eRet = RTSPSVR_ERR_SMS; 
		}
	}else{
		if( (NULL == pctEnv) ){
			printf("[%s]pctEnv is null\n", 
				__func__);
			eRet = RTSPSVR_ERR_SMS;
		}
	}
	return eRet;
}

RTSPSVR_ERR_et 
	RealTimeRtspServer::eAddSMSSToSMS(
	ServerMediaSubsession* pctSMSS)
{
	RTSPSVR_ERR_et eRet = RTSPSVR_ERR_NOERR;
	if( (NULL != pctSms) && (NULL != pctSMSS) ){
		pctSms->addSubsession(pctSMSS);
	}else{
		printf("[%s]add SMSS failed\n", __func__);
		eRet = RTSPSVR_ERR_ASMSS;
	}
	return eRet;
}

RTSPSVR_ERR_et 
	RealTimeRtspServer::eAddSMSToRtspSvr()
{
	RTSPSVR_ERR_et eRet = RTSPSVR_ERR_NOERR;
	if( (NULL != pctSms) && (NULL != pctRtspSvr) ){
		pctRtspSvr->addServerMediaSession(pctSms);
	}else{
		printf("[%s]add SMSS failed\n", __func__);
		eRet = RTSPSVR_ERR_ASMS;
	}
	return eRet;
}


const char *
	RealTimeRtspServer::pcGetRtspServerUrl()
{
	char * url = NULL;
	if( (NULL != pctSms) && (NULL != pctRtspSvr) ){
		url = pctRtspSvr->rtspURL(pctSms);
	}else{
		printf("[%s]get rtsp server url failed\n", 
			__func__);
	}
	return url;
}

RTSPSVR_ERR_et 
	RealTimeRtspServer::eStartTaskScheduler()
{
	RTSPSVR_ERR_et eRet = RTSPSVR_ERR_NOERR;
	cExitFlag = 0;
	if( (NULL != pctEnv) ){
		pctEnv->taskScheduler().doEventLoop(
			&cExitFlag);
	}else{
		printf("[%s]pctEnv is null\n", __func__);
		eRet = RTSPSVR_ERR_TASK;
	}
	return eRet;
}
